package com.ruoyi.system.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Docker迁移日志工具类
 * 用于记录Docker容器和镜像迁移过程中的详细日志
 */
public class DockerMigrationLogger {
    private static final Logger log = LoggerFactory.getLogger("docker-migration");
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    
    // 部署日志缓存，key为serverId_processId
    private static final Map<String, List<String>> deployLogsCache = new ConcurrentHashMap<>();
    // 部署状态缓存，key为serverId_processId
    private static final Map<String, Boolean> deployCompletedCache = new ConcurrentHashMap<>();
    // 部署结果缓存，key为serverId_processId
    private static final Map<String, Boolean> deploySuccessCache = new ConcurrentHashMap<>();
    // 缓存过期时间（毫秒）
    private static final long CACHE_EXPIRE_TIME = 30 * 60 * 1000; // 30分钟
    // 缓存创建时间，key为serverId_processId
    private static final Map<String, Long> cacheCreateTimeMap = new ConcurrentHashMap<>();

    /**
     * 记录开始迁移容器的信息
     * 
     * @param sourceServerId 源服务器ID
     * @param targetServerId 目标服务器ID
     * @param containerId 容器ID
     */
    public static void logContainerMigrationStart(Long sourceServerId, Long targetServerId, String containerId) {
        String message = String.format("[容器迁移开始] 源服务器ID: %d, 目标服务器ID: %d, 容器ID: %s, 时间: %s", 
            sourceServerId, targetServerId, containerId, getCurrentTime());
        log.info(message);
    }

    /**
     * 记录迁移容器过程中的详细步骤
     * 
     * @param sourceServerId 源服务器ID
     * @param targetServerId 目标服务器ID
     * @param containerId 容器ID
     * @param step 步骤名称
     * @param details 详细信息
     */
    public static void logContainerMigrationStep(Long sourceServerId, Long targetServerId, String containerId, 
                                              String step, String details) {
        String message = String.format("[容器迁移步骤] 源服务器ID: %d, 目标服务器ID: %d, 容器ID: %s, 步骤: %s, 详情: %s, 时间: %s", 
            sourceServerId, targetServerId, containerId, step, details, getCurrentTime());
        log.info(message);
        
        // 如果是部署步骤，添加到部署日志缓存
        if (step != null && step.contains("部署")) {
            addToDeployLogs(sourceServerId, containerId, "[步骤] " + step + ": " + details);
        }
    }

    /**
     * 记录迁移容器结束的信息
     * 
     * @param sourceServerId 源服务器ID
     * @param targetServerId 目标服务器ID
     * @param containerId 容器ID
     * @param success 是否成功
     * @param message 额外信息
     */
    public static void logContainerMigrationEnd(Long sourceServerId, Long targetServerId, String containerId, 
                                            boolean success, String message) {
        String logMessage = String.format("[容器迁移%s] 源服务器ID: %d, 目标服务器ID: %d, 容器ID: %s, 信息: %s, 时间: %s", 
            success ? "成功" : "失败", sourceServerId, targetServerId, containerId, message, getCurrentTime());
        if (success) {
            log.info(logMessage);
        } else {
            log.error(logMessage);
        }
        
        // 记录部署完成状态
        String processId = containerId;
        if (processId != null) {
            String key = getDeployLogKey(sourceServerId, processId);
            deployCompletedCache.put(key, true);
            deploySuccessCache.put(key, success);
            addToDeployLogs(sourceServerId, processId, "[完成] 部署" + (success ? "成功" : "失败") + ": " + message);
        }
    }

    /**
     * 记录迁移过程中的异常
     * 
     * @param sourceServerId 源服务器ID
     * @param targetServerId 目标服务器ID
     * @param containerId 容器ID
     * @param step 步骤名称
     * @param e 异常
     */
    public static void logContainerMigrationException(Long sourceServerId, Long targetServerId, String containerId, 
                                                   String step, Exception e) {
        String message = String.format("[容器迁移异常] 源服务器ID: %d, 目标服务器ID: %d, 容器ID: %s, 步骤: %s, 异常: %s, 时间: %s", 
            sourceServerId, targetServerId, containerId, step, e.getMessage(), getCurrentTime());
        log.error(message, e);
        
        // 记录部署异常
        if (containerId != null) {
            addToDeployLogs(sourceServerId, containerId, "[异常] " + step + ": " + e.getMessage());
        }
    }

    /**
     * 记录命令执行信息
     * 
     * @param serverId 服务器ID
     * @param command 执行的命令
     * @param success 是否成功
     * @param output 输出结果
     */
    public static void logCommandExecution(Long serverId, String command, boolean success, String output) {
        String message = String.format("[命令执行%s] 服务器ID: %d, 命令: %s, 输出: %s, 时间: %s", 
            success ? "成功" : "失败", serverId, command, output, getCurrentTime());
        if (success) {
            log.info(message);
        } else {
            log.error(message);
        }
        
        // 记录命令执行到部署日志
        // 这里使用当前时间戳作为processId，实际使用时应该传入真实的processId
        String processId = String.valueOf(System.currentTimeMillis());
        addToDeployLogs(serverId, processId, "[命令] " + command);
        if (output != null && !output.isEmpty()) {
            addToDeployLogs(serverId, processId, "[输出] " + output);
        }
    }

    /**
     * 添加部署日志
     * 
     * @param serverId 服务器ID
     * @param processId 部署过程ID
     * @param log 日志内容
     */
    public static void addToDeployLogs(Long serverId, String processId, String log) {
        if (serverId == null || processId == null) {
            return;
        }
        
        String key = getDeployLogKey(serverId, processId);
        deployLogsCache.computeIfAbsent(key, k -> new ArrayList<>()).add(log);
        cacheCreateTimeMap.putIfAbsent(key, System.currentTimeMillis());
        
        // 清理过期缓存
        cleanExpiredCache();
    }
    
    /**
     * 获取部署日志
     * 
     * @param serverId 服务器ID
     * @param processId 部署过程ID
     * @return 日志列表
     */
    public static List<String> getDeployLogs(Long serverId, String processId) {
        if (serverId == null || processId == null) {
            return new ArrayList<>();
        }
        
        String key = getDeployLogKey(serverId, processId);
        return deployLogsCache.getOrDefault(key, new ArrayList<>());
    }
    
    /**
     * 判断部署是否完成
     * 
     * @param serverId 服务器ID
     * @param processId 部署过程ID
     * @return 是否完成
     */
    public static boolean isDeployCompleted(Long serverId, String processId) {
        if (serverId == null || processId == null) {
            return false;
        }
        
        String key = getDeployLogKey(serverId, processId);
        return deployCompletedCache.getOrDefault(key, false);
    }
    
    /**
     * 判断部署是否成功
     * 
     * @param serverId 服务器ID
     * @param processId 部署过程ID
     * @return 是否成功
     */
    public static boolean isDeploySuccess(Long serverId, String processId) {
        if (serverId == null || processId == null) {
            return false;
        }
        
        String key = getDeployLogKey(serverId, processId);
        return deploySuccessCache.getOrDefault(key, false);
    }
    
    /**
     * 清理过期缓存
     */
    private static void cleanExpiredCache() {
        long now = System.currentTimeMillis();
        List<String> expiredKeys = new ArrayList<>();
        
        for (Map.Entry<String, Long> entry : cacheCreateTimeMap.entrySet()) {
            if (now - entry.getValue() > CACHE_EXPIRE_TIME) {
                expiredKeys.add(entry.getKey());
            }
        }
        
        for (String key : expiredKeys) {
            deployLogsCache.remove(key);
            deployCompletedCache.remove(key);
            deploySuccessCache.remove(key);
            cacheCreateTimeMap.remove(key);
        }
    }
    
    /**
     * 获取部署日志缓存的key
     * 
     * @param serverId 服务器ID
     * @param processId 部署过程ID
     * @return 缓存key
     */
    private static String getDeployLogKey(Long serverId, String processId) {
        return serverId + "_" + processId;
    }

    /**
     * 获取当前时间字符串
     */
    private static String getCurrentTime() {
        return dateFormat.format(new Date());
    }
} 